﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using nHydrate.Dsl;
using System.IO;
using System.Xml;
using nHydrate.Generator.Common.Util;
using nHydrate.DslPackage.Forms;
using System.Windows.Forms;
using nHydrate.DslPackage.Objects;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace nHydrate.DslPackage
{
	partial class nHydrateDocData
	{
		public bool IsImporting { get; set; }

		protected override void OnDocumentLoaded()
		{
			base.OnDocumentLoaded();

			var modelRoot = this.RootElement as global::nHydrate.Dsl.nHydrateModel;
			nHydrate.Dsl.nHydrateDiagram diagram = null;
			if (modelRoot != null)
			{
				diagram = Microsoft.VisualStudio.Modeling.Diagrams.PresentationViewsSubject.GetPresentation(modelRoot).FirstOrDefault() as nHydrate.Dsl.nHydrateDiagram;
				//diagram.KeyDown += new Microsoft.VisualStudio.Modeling.Diagrams.DiagramKeyEventHandler(diagram_KeyDown);
				if (diagram != null)
				{
					diagram.ShapeDoubleClick += new EventHandler<nHydrate.Dsl.ModelElementEventArgs>(diagram_ShapeDoubleClick);
					diagram.ShapeConfiguring += new EventHandler<nHydrate.Dsl.ModelElementEventArgs>(diagram_ShapeConfiguring);
				}
			}

			if (diagram != null)
			{
				var mainInfo = new FileInfo(this.FileName);
				var modelName = mainInfo.Name.Replace(".nhydrate", ".model");
				nHydrate.Dsl.Custom.SQLFileManagement.LoadDiagramFiles(modelRoot, mainInfo.DirectoryName, modelName, diagram);
			}

			#region Load the delete tracking file
			var fi = new FileInfo(this.FileName);
			var cacheFile = Path.Combine(fi.DirectoryName, fi.Name + ".deletetracking");
			if (File.Exists(cacheFile))
			{
				var document = new XmlDocument();
				try
				{
					document.Load(cacheFile);
				}
				catch (Exception ex)
				{
					//Do Nothing, there is a file error
					return;
				}

				//Tables
				foreach (XmlNode node in document.DocumentElement.SelectNodes("tables/table"))
				{
					modelRoot.RemovedTables.Add(node.InnerText);
				}

				//Views
				foreach (XmlNode node in document.DocumentElement.SelectNodes("views/view"))
				{
					modelRoot.RemovedViews.Add(node.InnerText);
				}

				//Stored Procedures
				foreach (XmlNode node in document.DocumentElement.SelectNodes("storedprocedures/storedprocedure"))
				{
					modelRoot.RemovedStoredProcedures.Add(node.InnerText);
				}

				//Functions
				foreach (XmlNode node in document.DocumentElement.SelectNodes("functions/function"))
				{
					modelRoot.RemovedFunctions.Add(node.InnerText);
				}

			}
			#endregion

			modelRoot.IsDirty = false;
			modelRoot.IsLoading = false;
			this.SetDocDataDirty(0);

		}

		//private void diagram_KeyDown(object sender, Microsoft.VisualStudio.Modeling.Diagrams.DiagramKeyEventArgs e)
		//{
		//  if (e.Control && e.KeyCode == System.Windows.Forms.Keys.F)
		//  {
		//    // Get the instance number 0 of this tool window. This window is single instance so this instance
		//    // is actually the only one.
		//    // The last flag is set to true so that if the tool window does not exists it will be created.
		//    var window = new FindWindow();
		//    //var window = FindToolWindow(typeof(FindWindow), 0, true);
		//    //if ((null == window) || (null == window.Frame))
		//    //{
		//    //  throw new NotSupportedException();
		//    //}
		//    var windowFrame = (IVsWindowFrame)window.Frame;
		//    Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());

		//  }
		//}

		protected override void OnDocumentSaved(EventArgs e)
		{
			base.OnDocumentSaved(e);

			//Save the delete tracking file
			var modelRoot = this.RootElement as global::nHydrate.Dsl.nHydrateModel;
			var fi = new FileInfo(this.FileName);
			var cacheFile = Path.Combine(fi.DirectoryName, fi.Name + ".deletetracking");
			if (File.Exists(cacheFile)) File.Delete(cacheFile);
			if ((modelRoot.RemovedTables.Count +
				modelRoot.RemovedViews.Count +
				modelRoot.RemovedStoredProcedures.Count +
				modelRoot.RemovedFunctions.Count) > 0)
			{
				var document = new XmlDocument();
				document.LoadXml("<root></root>");
				var tableRoot = XmlHelper.AddElement(document.DocumentElement, "tables") as XmlElement;
				var viewRoot = XmlHelper.AddElement(document.DocumentElement, "views") as XmlElement;
				var storedProcedureRoot = XmlHelper.AddElement(document.DocumentElement, "storedprocedures") as XmlElement;
				var functionRoot = XmlHelper.AddElement(document.DocumentElement, "functions") as XmlElement;

				//Tables
				foreach (var item in modelRoot.RemovedTables)
				{
					XmlHelper.AddElement(tableRoot, "table", item);
				}

				//Views
				foreach (var item in modelRoot.RemovedViews)
				{
					XmlHelper.AddElement(viewRoot, "view", item);
				}

				//Stored Procedures
				foreach (var item in modelRoot.RemovedStoredProcedures)
				{
					XmlHelper.AddElement(storedProcedureRoot, "storedprocedure", item);
				}

				//Functions
				foreach (var item in modelRoot.RemovedFunctions)
				{
					XmlHelper.AddElement(functionRoot, "function", item);
				}

				document.Save(cacheFile);
			}

		}

		private void diagram_ShapeConfiguring(object sender, nHydrate.Dsl.ModelElementEventArgs e)
		{
			if (this.IsImporting) return;

			var diagram = (((Microsoft.VisualStudio.Modeling.Shell.SingleDiagramDocView)(this.DocViews.First())).CurrentDiagram);
			var shape = e.Shape;

			if (shape is EntityAssociationConnector)
			{
				var F = new nHydrate.DslPackage.Forms.RelationshipDialog(shape.Diagram.ModelElement as nHydrateModel, shape.Store, shape as EntityAssociationConnector);
				if (F.ShowDialog() != System.Windows.Forms.DialogResult.OK)
				{
					var relation = shape.ModelElement as EntityHasEntities;
					relation.ParentEntity.ChildEntities.Remove(relation.ParentEntity.ChildEntities.LastOrDefault());
				}
			}
			//else if (shape is EntityInheritanceConnector)
			//{
			//  var F = new nHydrate.DslPackage.Forms.RelationshipDialog(shape.Diagram.ModelElement as nHydrateModel, shape.Store, shape as EntityInheritanceConnector);
			//  if (F.ShowDialog() != System.Windows.Forms.DialogResult.OK)
			//  {
			//    var relation = shape.ModelElement as EntityInheritsEntity;
			//    relation.ParentInheritedEntityY.ChildDerivedEntitiesY.Remove(relation.ParentInheritedEntityY.ChildDerivedEntitiesY.LastOrDefault());
			//  }
			//}

		}

		private void diagram_ShapeDoubleClick(object sender, nHydrate.Dsl.ModelElementEventArgs e)
		{
			var diagram = (((Microsoft.VisualStudio.Modeling.Shell.SingleDiagramDocView)(this.DocViews.First())).CurrentDiagram);
			var shape = e.Shape;

			if (shape is EntityAssociationConnector)
			{
				if (!(shape.Diagram as nHydrateDiagram).IsLoading)
				{
					var F = new nHydrate.DslPackage.Forms.RelationshipDialog(shape.Diagram.ModelElement as nHydrateModel, shape.Store, shape as EntityAssociationConnector);
					F.ShowDialog();
				}
			}
			//else if (shape is EntityInheritanceConnector)
			//{
			//  var F = new nHydrate.DslPackage.Forms.RelationshipDialog(shape.Diagram.ModelElement as nHydrateModel, shape.Store, shape as EntityInheritanceConnector);
			//  F.ShowDialog();
			//}
			//else if (shape is EntityShape)
			//{
			//  var F = new nHydrate.DslPackage.Forms.RelationCollectionForm(shape.Diagram.ModelElement as nHydrateModel, shape as EntityShape, shape.Store, shape.Diagram);
			//  F.ShowDialog();
			//}

		}

	}

	partial class nHydrateExplorerToolWindow
	{
		public override System.ComponentModel.Design.IMenuCommandService MenuService
		{
			get { return base.MenuService; }
		}

		protected override void OnSelectionChanged(EventArgs e)
		{
			base.OnSelectionChanged(e);
		}

	}

	partial class nHydrateDocData
	{
		protected override void OnDocumentLoaded(EventArgs e)
		{
			base.OnDocumentLoaded(e);
		}

		protected override void Save(string fileName)
		{
			var key = ProgressHelper.ProgressingStarted("Saving Model...", true);
			try
			{
				base.Save(fileName);
			}
			catch (Exception ex)
			{
				ProgressHelper.ProgressingComplete(key);
				throw;
			}
			finally
			{
				ProgressHelper.ProgressingComplete(key);
			}

		}

		protected override void Load(string fileName, bool isReload)
		{
			var key = ProgressHelper.ProgressingStarted("Loading Model...", true);
			nHydrateModel modelRoot = null;
			try
			{
				base.Load(fileName, isReload);

				modelRoot = this.RootElement as nHydrateModel;
				if (modelRoot.IsDirty)
				{
					this.SetDocDataDirty(0);
					ProgressHelper.ProgressingComplete(key);
					//this.SetDocDataDirty(1);
					//if (modelRoot.ModelToDisk)
					//  MessageBox.Show("One or more of the model managed files have changed. The model has been updated but you must save this model to persist changes to disk.", "Model Changed", MessageBoxButtons.OK, MessageBoxIcon.Information);
				}
			}
			catch (Exception ex)
			{
				ProgressHelper.ProgressingComplete(key);
				throw;
			}
			finally
			{
				ProgressHelper.ProgressingComplete(key);
				//if (modelRoot != null)
				//  modelRoot.IsLoading = false;
			}
		}

	}

	//http://www.code-magazine.com/article.aspx?quickid=0710072&page=2
	partial class nHydratePackage
	{
		protected override void Initialize()
		{
			base.Initialize();
		}
	}

}